#include<iostream>
#include<vector>
using namespace std;

//template<class T, size_t N = 10>
//class Stack
//{
//public:
//	void func() { N++; }
//private:
//	int _a[N];
//	int _top;
//};
//
//// 函数模板
//template<class T>
//bool Less(T left, T right)
//{
//	return left < right;
//}
//
//// 函数模板特化
//void PrintVector(const vector<int>& v)
//{
//	vector<int>::const_iterator it = v.begin();
//	while (it != v.end())
//	{
//		cout << *it << " ";
//		++it;
//	}
//	cout << endl;
//}
//
//template<class T>
//void PrintVector(const vector<T>& v)
//{
//	//模板没实例化时，不去里面查细节的东西，无法确认是类型还是静态变量
//	//加typename明确告诉编译器是类型
//	typename vector<T>::const_iterator it = v.begin();
//	while (it != v.end())
//	{
//		cout << *it << " ";
//		++it;
//	}
//	cout << endl;
//}
//
////int main()
////{
////	vector<int> v1 = { 1,2,3,4,5,6,7 };
////	vector<double> v2{ 1.1,2.2,3.3,4.4,5.5,6.6,7.7 };
////	PrintVector(v1);
////	PrintVector(v2);
////
////	return 0;
////}
//
//
//#include<vector>
//#include<algorithm>
//
//template<class T1, class T2>
//class Date
//{
//public:
//	Data() { cout << "Data<T1, T2>-原模版" << endl; }
//private:
//	T1 _d1;
//	T2 _d2;
//};
//
////一个引用 一个指针
//template<typename T1, typename T2>
//class Date<T1&, T2*>
//{
//public:
//	Data()
//	{
//		cout << typeid(T1).name() << endl;
//		cout << typeid(T2).name() << endl;
//		cout << "Data<T1&,T2&>-偏特化引用" << endl;
//	}
//};
//


// 继承
//class Person
//{
//public:
//	void Print()
//	{
//		cout << "name:" << _name << endl;
//		cout << "age:" << _age << endl;
//	}
//protected:
//	string _name = "xiaolufei";
//	int _age = 18;
//
//private:
//	int _tel = 100;
//};
//
//class Student : public Person
//{
//protected:
//	int _stuid;
//};
//
//class Teacher : public Person
//{
//protected:
//	int _jobid;
//};
//
//int main()
//{
//	Student s;
//	Teacher t;
//	s.Print();
//	t.Print();
//
//	return 0;
//}

//class Person
//{
//public:
//	void Print()
//	{
//		cout << "name:" << _name << endl;
//		cout << "age:" << _age << endl;
//		cout << "tel:" << _tel << endl;
//	}
//
//	string _name = "Luffty";
//	int _age = 18;
//private:
//	int _tel = 100;
//};
//
//class Student : public Person
//{
//public:
//	void func()
//	{
//
//		cout << _name << endl;
//		cout << _age << endl;
//
//	}
//protected:
//	int _stuid;//学号
//};
//
//class Teacher : public Person
//{
//protected:
//	int _jobid;//工号
//};
//
//int main()
//{
//	Person p;
//	p._name = "小张";
//	p.Print();
//
//	Student s;
//	s._name = "张三";
//	s.Print();
//
//	Teacher t;
//	t._name = "张老师";
//	t.Print();
//
//	return 0;
//}

// 赋值兼容转换不会产生临时变量
//class Person
//{
//protected:
//	string _name; // 姓名
//	string _sex;// 性别
//	int _age; // 年龄
//};
//class Student : public Person
//{
//public:
//	int _No; // 学号
//};
//void Test()
//{
//	Student sobj;
//	// 1.子类对象可以赋值给父类对象/指针/引用
//	Person pobj = sobj;
//	Person* pp = &sobj;
//	Person& rp = sobj;
//
//	//2.基类对象不能赋值给派生类对象
//	//sobj = pobj;
//
//	// 3.基类的指针可以通过强制类型转换赋值给派生类的指针
//	pp = &sobj;
//	Student* ps1 = (Student*)pp; // 这种情况转换时可以的。
//	ps1->_No = 10;
//
//	//pp = &pobj;
//	//Student* ps2 = (Student*)pp; // 这种情况转换时虽然可以，但是会存在越界访问的问题
//	//ps2->_No = 10;
//}
//int main()
//{
//	Test();
//	return 0;
//}

//class Person
//{
//protected:
//	string _name = "小李子"; // 姓名
//	int _num = 111;// 身份证号
//};
//class Student : public Person
//{
//public:
//	void Print()
//	{
//		cout << " 姓名:" << _name << endl;
//		//cout << " 身份证号:" << Person::_num << endl;//指定访问父类
//		cout << " 学号:" << _num << endl;//默认访问到子类的，隐藏/重定义
//		cout << " 学号:" << Person::_num << endl;// 访问父类要指定类域
//	}
//protected:
//	int _num = 999; // 学号
//};
//int main()
//{
//	Student s1;//当子类和父类有相同的成员，先在自己的域里面查找_num，再去父类里面找
//	s1.Print();
//
//	return 0;
//}

// 派生类的默认成员函数
//class Person
//{
//public:
//	//Person(const char* name = "")//全缺省（默认构造：无参的、全缺省的）
//	Person(const char* name)//带参构造 ，此时没有默认构造，编译器会自动生成，此时就要在子类显式写默认构造
//		: _name(name)
//	{
//		cout << "Person()" << endl;
//	}
//
//	Person(const Person& p)
//		: _name(p._name)
//	{
//		cout << "Person(const Person& p)" << endl;
//	}
//
//	Person& operator=(const Person& p)
//	{
//		cout << "Person operator=(const Person& p)" << endl;
//		if (this != &p)
//			_name = p._name;
//
//		return *this;
//	}
//
//	~Person()
//	{
//		cout << "~Person()" << endl;
//		delete[] _str;//
//	}
//protected:
//	string _name; // 姓名
//
//	char* _str = new char[10] {'x', 'y', 'z'};
//};
//
//class Student : public Person
//{
//public:
//	//Student(const char* name,int x,const char* address)
//	//	//:_name(name)//规定子类不能直接碰父类的成员
//	//	            //父类里面已经定义了构造（初始化父类里面的成员），
//	//	            //继承为什么不复用呢？所以不能碰父类的成员
//	//	:Person(name)//规定这样子调用
//	//	,_x(x)
//	//	, _addrss(address)
//	//{}
//
//	//显式写构造
//	//父类构造显示调用，可以保证先父后子
//	Student(const char* name = "", int x = 0, const char* address = "")
//		:Person(name)//调用用父类的拷贝构造，父类的拷贝构造的参数，得把子类对象当中父类的那一部分给切出来 
//		, _x(x)
//		, _addrss(address)
//	{}
//
//	//深拷贝
//	Student(const Student& st)
//		:Person(st) // 
//		, _x(st._x)
//		, _addrss(st._addrss)
//	{}
//
//	//赋值
//	Student& operator=(const Student& st)//子类的赋值跟父类的赋值构成隐藏关系（函数名相同就是隐藏）
//	{
//		if (this != &st)
//		{
//			Person::operator=(st);//子类调用父类，要指定作用域
//			_x = st._x;
//			_addrss = st._addrss;
//		}
//		return *this;
//	}
//
//	//析构
//	//由于多态，析构函数的名字会被统一成destructor(),因此父类的析构和子类的析构函数构成隐藏，所以复用时要指定作用域
//	//父类的析构不能显式调用，因为显式调用不能保证先子后父
//	~Student()
//	{
//		//析构函数会构成隐藏关系，所以这里要指定作用域
//		//Person::~Person();//析构函数不能显式调用，它会自动的去调用（规定的）
//							//它会在子类析构结束以后，自动调用，因此不用写，不然会重复析构
//							//为什么析构不能显式调用？
//							//
//		cout << "~Student()" << endl;
//		//delete [] _ptr;
//		//cout << _str << endl;//当显式调用析构时（先父类析构），父类的成员变量已经被析构了，此时程序出现错误 
//
//	}
//
//protected:
//	int _x;
//	string _addrss;
//
//	//int* _ptr = new int[10]; //此时涉及深浅拷贝的内部问题，要自己写深拷贝
//};
//
//int main()
//{
//	//默认构造
//	Student s1;
//	Student s2("小路飞", 2, "桂林市");
//
//	//拷贝构造
//	Student s3 = s2;//调用父类的拷贝构造 
//
//	s1 = s3;
//
//	return 0;
//}


// 继承与友元
//class Student;
//class Person
//{
//public:
//	friend void Display(const Person& p, const Student& s);
//protected:
//	string _name; // 姓名
//};
//class Student : public Person
//{
//public:
//	friend void Display(const Person& p, const Student& s);//要想有父类的友元，得自己写
//protected:
//	int _stuNum; // 学号
//};
//void Display(const Person& p, const Student& s)
//{
//	cout << p._name << endl;
//	cout << s._stuNum << endl;
//}
//int main()
//{
//	Person p;
//	Student s;
//	Display(p, s);
//
//	return 0;
//}

//继承与静态成员
//class Person
//{
//public:
//	Person() { ++_count; }
//protected:
//	string _name; // 姓名
//public:
//	static int _count; // 统计人的个数。
//};
//
//int Person::_count = 0;
//
//class Student : public Person
//{
//protected:
//	int _stuNum; // 学号
//};
//class Graduate : public Student
//{
//protected:
//	string _seminarCourse; // 研究科目
//};
//int main()
//{
//	//父类的静态成员和子类的静态成员指向同一个空间
//	Person p;
//	Student s;
//	cout << &Person::_count << endl;
//	cout << &Student::_count << endl;
//
//	return 0;
//}

//菱形继承
//class Person
//{
//public:
//	//这些信息都会有多份，会造成二义性，因此访问时要指定类域
//	string _name; // 姓名
//	int _id;
//	int _tel;
//	int _address;
//};
//
//class Student : public Person
//{
//protected:
//	int _num; //学号
//};
//
//class Teacher : public Person
//{
//protected:
//	int _id; // 职工编号
//};
//
//class Assistant : public Student, public Teacher
//{
//protected:
//	string _majorCourse; // 主修课程
//};
//
//int main()
//{
//	//数据冗余和二义性
//	// 这样会有二义性无法明确知道访问的是哪一个
//	Assistant a;
//	//a._name = "peter";
//
//	//当Person越大数据冗余也就越大（浪费空间）
//	// 需要显示指定访问哪个父类的成员可以解决二义性问题，但是数据冗余问题无法解决
//	a.Student::_name = "小李";
//	a.Teacher::_name = "李老师";
//
//	return 0;
//}

// 虚继承---解决菱形继承中出现的数据冗余和二义性的问题
//class Person
//{
//public:
//	string _name; // 姓名
//};
//
//class Student : virtual public Person
//{
//protected:
//	int _num; //学号
//};
//
//class Teacher : virtual public Person
//{
//protected:
//	int _id; // 职工编号
//};
//
//class Assistant : public Student, public Teacher
//{
//protected:
//	string _majorCourse; // 主修课程
//};
//
//int main()
//{
//	Assistant a;
//	a.Student::_name = "小李";
//	a.Teacher::_name = "李老师";
//	//此时可以不指定类域（虚继承已经解决冗余和二义性）
//	a._name = "李益达";
//
//	return 0;
//}


// 组合
 // Car和BMW Car和Benz构成is-a的关系  （继承）
//class Car {
//protected:
//    string _colour = "白色"; // 颜色
//    string _num = "陕ABIT00"; // 车牌号
//};
//
//class BMW : public Car {
//public:
//    void Drive() { cout << "好开-操控" << endl; }
//};
//
//class Benz : public Car {
//public:
//    void Drive() { cout << "好坐-舒适" << endl; }
//};
//
//
//// Tire和Car构成has-a的关系  （组合）
//
//class Tire {
//protected:
//    string _brand = "Michelin";  // 品牌
//    size_t _size = 17;         // 尺寸
//
//};
//
//class Car {
//protected:
//    string _colour = "白色"; // 颜色
//    string _num = "陕ABIT00"; // 车牌号
//    Tire _t; // 轮胎
//};

//多态
//class A
//{
//public:
//	virtual void test() { cout << "A: test()" << endl; }
//};
//
//class B : public A
//{
//public:
//	virtual void test() { cout << "B: test()" << endl; }
//};

// 通过基类的指针或者引用调用虚函数
//void func(A& x) { x.test(); }
//
//void main()
//{
//	A a;
//	func(a);
//
//	B b;
//	func(b); 
//}

// 非多态
//void func(A x) { x.test(); }
//void main()
//{
//	A a;
//	func(a);
//
//	B b;
//	func(b);
//}

// 虚函数的重写
//class Person
//{
//public:
//	virtual void BuyTick() { cout << "买票--全价" << endl; }
//};
//
//class Student : public Person
//{
//public:
//	virtual void BuyTick() { cout << "买票--半价" << endl; }
//};
//
//void Func(Person& p) { p.BuyTick(); }

//int main()
//{
//	Person p;
//	Student s;
//
//	Func(p);
//	Func(s);
//
//	return 0;
//}

// 协变
//class A {};
//
//class B : public A {};
//
//class Person
//{
//public:
//	virtual A* f() { return new A; }
//};
//
//class Student : public Person
//{
//public:
//	virtual B* f() { return new B; }
//};

// 析构函数的重写
//class Person
//{
//public:
//	virtual ~Person() { cout << "~Person()" << endl; }
//};
//
//class Student : public Person
//{
//public:
//	virtual ~Student() { cout << "~Student()" << endl; }
//};
//
//int main()
//{
//	Person* p1 = new Person;
//	Person* p2 = new Student;
//
//	delete p1;
//	delete p2;
//
//	return 0;
//}

//class Person {
//public:
//	virtual ~Person()
//	{
//		cout << "~Person()" << endl;
//	}
//};
//
//class Student : public Person {
//public:
//	virtual ~Student()
//	{
//		cout << "~Student()" << endl;
//	}
//};
//
//int main()
//{
//	Student s;//加不加 virtaul 普通对象都不受影响 
//	//析构先调用子类析构，在调用父类析构
//	//所以说在子类/派生类结束了以后会自动调用父类的析构
//	//派生类里面有一个父类对象
//
//	return 0;
//}

// 内存泄露
// 为什么析构函数一定建议设计成虚函数？
//class Person
//{
//public:
//	  ~Person() { cout << "~Person()" << endl; }
//	 //virtual ~Person() { cout << "~Person()" << endl; }
//};
//
//class Student : public Person
//{
//public:
//	 ~Student()
//	//virtual ~Student()
//	{
//		delete _ptr;
//		cout << "~Student():" << _ptr <<endl;
//	}
//
//protected:
//	int* _ptr = new int[10];
//};
//
//int main()
//{
//	Person* p1 = new Student;
//	delete p1;
//
//	Person* p2 = new Person;// 调用父类的析构，但不会自动调用子类的析构
//	delete p2;// 可能造成子类参数的内存泄露
//
//	return 0;
//}

// final: 修饰虚函数，表示虚函数不能再被重写
//class Person {
//public:
//	virtual ~Person()  final //不想被完成重写，此时子类就不能被重写
//	{
//		cout << "~Person()" << endl;
//	}
//};
//
//class Student : public Person {
//public:
//	~Student() //报错，不能完成重写
//	{
//		delete _ptr;
//		cout << "~Student()：" << _ptr << endl;
//	}
//protected:
//	int* _ptr = new int[10];
//};
//
//
//int main()
//{
//
//	Person* p1 = new Student;
//	delete p1;
//
//	Person* p2 = new Person;
//	delete p2;
//
//	return 0;
//}


// override：检查派生类虚函数是否重写了基类的某个函数，如果没有1重写编译报错
//class Person {
//public:
//	~Person()//没有完成重写
//	{
//		cout << "~Person()" << endl;
//	}
//};
//
//class Student : public Person {
//public:
//	~Student() override //检查派生类是否完成重写，没有完成就报错
//	{
//		delete _ptr;
//		cout << "~Student()：" << _ptr << endl;
//	}
//protected:
//	int* _ptr = new int[10];
//};
//
//
//int main()
//{
//	Person* p1 = new Student;
//	delete p1;
//
//	Person* p2 = new Person;
//	delete p2;
//
//	return 0;
//}

// 抽象类： 不能实例化出对象
//class Car
//{
//public:
//	virtual void Drive() = 0;// 纯虚函数
//};
//
//class Benz : public Car
//{
//public:
//	virtual void Drive()//重写虚函数
//	{
//		cout << "Benz-舒适" << endl;
//	}
//};
//
//class BMW : public Car
//{
//public:
//	virtual void Drive() { cout << "BMW - 操控" << endl; }
//};
//
//int main()
//{
//	Benz bz;
//
//	Car* pBenz = new Benz;
//	pBenz->Drive();
//	Car* pBMW = new BMW;
//	pBMW->Drive();
//
//	return 0;
//}


//多态原理
class Base
{
public:
	virtual void Func1() { cout << "Func1()" << endl; }
	virtual void Func2() { cout << "Func2()" << endl; }
	 void Func3() { cout << "Func3()" << endl; }
private:
	int _b = 1;
};

class Derive : public Base
{
public:
	virtual void Func1()
	{
		cout << "Derive::Func1()" << endl;
	}
private:
	int _d = 2;
};

void Func1(Base* p)
{
	p->Func1();

	p->Func3();
}

int main()
{
	/*Base b;
	cout << sizeof(Base) << endl;*/

	Base b;
	Derive d;
	Func1(&b);
	Func1(&d);

	return 0;
}